package com.ym.wcp.framework.utils;

import org.apache.ibatis.exceptions.TooManyResultsException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.multipart.support.MissingServletRequestPartException;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.sql.SQLException;
import java.util.List;
import java.util.stream.Collectors;

public class ExceptionInfoUtil {

    /**
     * 打印Exception详细信息
     */
    public static String printStackTrace(Exception e) {
        if (e instanceof DuplicateKeyException) {
            return "数据已存在";
        } else if (e instanceof HttpMessageNotReadableException) {
            return "JSON解析异常";
        } else if (e instanceof TooManyResultsException) {
            return "结果集条数超出预期";
        } else if (e instanceof MethodArgumentTypeMismatchException) {
            MethodArgumentTypeMismatchException ex = (MethodArgumentTypeMismatchException) e;
            return String.format("参数[%s]的传入值:[%s]与预期的字段类型:[%s]不匹配", ex.getName(), ex.getValue(), ex.getRequiredType().getName());
        } else if (e instanceof MissingServletRequestParameterException) {
            MissingServletRequestParameterException ex = (MissingServletRequestParameterException) e;
            return String.format("缺少必须的[%s]类型的参数[%s]", ex.getParameterType(), ex.getParameterName());
        } else if (e instanceof HttpMediaTypeNotSupportedException) {
            HttpMediaTypeNotSupportedException ex = (HttpMediaTypeNotSupportedException) e;
            return String.format("请求类型Content-Type[%s]与实际接口的请求类型不匹配", ex.getContentType());
        } else if (e instanceof MissingServletRequestPartException) {
            MissingServletRequestPartException ex = (MissingServletRequestPartException) e;
            String requestPart = ex.getRequestPartName();
            return String.format("缺少必须的[%s]参数", requestPart);
        } else if (e instanceof MultipartException) {
            return "文件上传错误";
        } else if (e instanceof HttpRequestMethodNotSupportedException) {
            HttpRequestMethodNotSupportedException ex = (HttpRequestMethodNotSupportedException) e;
            return String.format("请求方法[%s]不受支持,请使用[%s]方法", ex.getMethod(), ex.getSupportedMethods()[0]);
        } else if (e instanceof BindException) {
            BindException ex = (BindException) e;
            String errMsg = getMessageByBindingResult(ex.getBindingResult());
            return StringUtils.isEmpty(errMsg) ? ex.getMessage() : errMsg;
        } else if (e instanceof ConstraintViolationException) {
            ConstraintViolationException ex = (ConstraintViolationException) e;
            return ex.getConstraintViolations().stream().map(ConstraintViolation::getMessage).collect(Collectors.joining());
        } else if (e instanceof MethodArgumentNotValidException) {
            MethodArgumentNotValidException ex = (MethodArgumentNotValidException) e;
            String errMsg = getMessageByBindingResult(ex.getBindingResult());
            return StringUtils.isEmpty(errMsg) ? ex.getMessage() : errMsg;
        } else if (e instanceof IllegalArgumentException) {
            return "参数不合法";
        } else if (e instanceof SQLException || e instanceof BadSqlGrammarException) {
            return "SQL语句错误";
        } else {
            String errMsg = StringUtils.isEmpty(e.getMessage()) ? e.getLocalizedMessage() : e.getMessage();
            if (errMsg.contains("Duplicate")) {
                return "数据已存在";
            }
            return errMsg;
        }
    }

    private static String getMessageByBindingResult(BindingResult bindingResult) {
        StringBuilder str = new StringBuilder();
        List<FieldError> fieldErrors = bindingResult.getFieldErrors();
        if (fieldErrors != null && fieldErrors.size() > 0) {
            for (FieldError fieldError : fieldErrors) {
                str.append(fieldError.getDefaultMessage());
            }
        } else {
            List<ObjectError> allErrors = bindingResult.getAllErrors();
            if (allErrors != null && allErrors.size() > 0) {
                for (ObjectError allError : allErrors) {
                    str.append(allError.getDefaultMessage());
                }
            }
        }

        return str.toString();
    }
}
